package com.ruoyi.web.controller.system;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.chinaums.open.api.OpenApiCache;
import com.chinaums.open.api.OpenApiContext;
import com.chinaums.open.api.constants.ConfigBean;
import com.chinaums.open.api.internal.util.http.HttpTransport;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.bank.BankCreditCard;
import com.ruoyi.system.domain.bank.SyUserLog;
import com.ruoyi.system.domain.bank.SysBank;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.service.ISysDeptService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

/**
 * api
 *
 * @author Lion Li
 */
@Validated
@RequiredArgsConstructor
@RestController
@SaIgnore
@RequestMapping("/bank/v1")
public class BankApiController extends BaseController {
    private final SysDeptMapper sysDeptMapper;
    private final ISysDeptService deptService;


    static String appId = "8a81c1bf89b6ccf7018b5b30aac10b83";
    static String appKey = "0489f0e4963f4fdcb62c3b6d46755772";
    static String termBatchNoOut = "000001";

    static String merchantCode="8984601701199KU";
    static String terminalCode="84JZ80E9";
    static String transactionCurrencyCode="156";
    static String ip="112.66.183.207";
    static  String deviceType="11";



    // 定义格式化器
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HHmmss");


    /**
     * 签到
     */
    @GetMapping("/sign")
    public R<Object> sign(String termNoIn, String mchntNoIn) {

        String url = "https://api-mop.chinaums.com/v1/upsc/signservice/sign";

        String now = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMAT);

        JSONObject json = new JSONObject();
        json.set("termNoIn", termNoIn);
        json.set("mchntNoIn", mchntNoIn);
        json.set("transType", "signin");
        json.set("networkNo", "003");
        json.set("termVersion", "32");
        json.set("transOrderId", now);


        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
        String authorization = getAuthorization(appId, appKey, now, IdUtil.fastSimpleUUID(), JSONUtil.toJsonStr(json));

        String re = HttpRequest.post(url)
            .body(JSONUtil.toJsonStr(json))
            .header("authorization", authorization).execute().body();

        JSONObject rejson = JSONUtil.parseObj(re);
        termBatchNoOut = rejson.getStr("termBatchNoOut");
        return R.ok("操作成功", re);
    }


    @GetMapping("/preauthcmp") //预授权完成
    public R<Object> preauthcmp(String termNoIn, String mchntNoIn,
                                String transAmt, String authNo, String priAcctNoHit,String params) {

        String url = "https://api-mop.chinaums.com/v1/upsc/preauthservice/preauthcmp";

        String now = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMAT);
        String year = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_FORMAT);
        int randomNumber = ThreadLocalRandom.current().nextInt(100000, 999999);
        String transOrderId = year + termBatchNoOut + randomNumber;
        JSONObject json = new JSONObject();
        json.set("termNoIn", termNoIn);
        json.set("mchntNoIn", mchntNoIn);
        json.set("transType", "auth.cmp");
        json.set("posEntryModeCode", "012");
//        json.set("transAmt", transAmt);
        BigDecimal s=new BigDecimal(transAmt).multiply(new BigDecimal("100")).setScale(0);
        json.set("transAmt", s.toString());
        json.set("currency", "156");
        json.set("termRead", "6");
        json.set("termVersion", "32");
        json.set("authNo", authNo);
        json.set("transOrderId", transOrderId);
        json.set("priAcctNoHit", priAcctNoHit);
//        json.set("oriPlatOrderId", "135959241150");


        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
        String authorization = getAuthorization(appId, appKey, now, IdUtil.fastSimpleUUID(), JSONUtil.toJsonStr(json));

        String re = HttpRequest.post(url)
            .body(JSONUtil.toJsonStr(json))
            .header("authorization", authorization).execute().body();
            Map<String,String> map=(Map) JSONUtil.parseObj(re);
            String respCodeDesc=map.get("respCodeDesc");

        if (respCodeDesc.equals("交易成功")) {
            try {
                String platOrderId=map.get("platOrderId"); //原订单号
                Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");


                String urls = "jdbc:sqlserver://127.0.0.1:1433;DatabaseName=Production;trustServerCertificate=true;";
                Connection conn = DriverManager.getConnection(urls, "sa", "xuquan666");

                String[] paramList = params.split(",");
                String reservationCode = paramList[0];   //预定号
                System.out.println(reservationCode + "这是预定号");

                String Amount = paramList[2];  //金额
//                int AmountStem=Integer.parseInt(Amount);
                String creditCardNo = paramList[3];  //银行卡
                String approveCode=paramList[4];  //授权号
                 String banTrxCode = paramList[1];  //主键
//                String voucherNo =paramList[5];

                PreparedStatement ps = conn.prepareStatement("{call dbo.ftPayment(?,?,?,?,?,?,?,?,?,?,?)}");
                ps.setString(1, "9004");
                ps.setString(2, Amount);
                ps.setString(3, "0|0|0");
                ps.setString(4,approveCode);  //入账的备注
                ps.setString(5, null);
                ps.setString(6, null);
                ps.setString(7, "*");
                ps.setString(8, "*");
                ps.setInt(9, 1);
                ps.setInt(10, Integer.parseInt(reservationCode));
                ps.setString(11, "Admin");
                ps.execute();


                PreparedStatement pstow = conn.prepareStatement("{call dbo.FTPaymentUpdate(?,?,?,?,?,?)}");
                pstow.setString(1, "9004");
                pstow.setString(2,Amount);
                pstow.setString(3, creditCardNo);
                pstow.setString(4, reservationCode);
                pstow.setString(5, "Admin");
                pstow.setString(6, banTrxCode);
                pstow.execute();


//                sysDeptMapper.getSysRvBankCreditCard(creditCardNo);查询卡号加*号接口
                deptService.updateBankCard(platOrderId, banTrxCode);  //保存 原订单号 在预授权完成撤销时使用
                deptService.updateBankReam("预授权完成",banTrxCode);                                     //通过bantrxcode更新rvcreditcard的remark字段 提醒用户 预授权状态 ‘这里是预授权完成’

                ps.close();
                pstow.close();
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                return R.ok("接口异常"+e.getMessage(), null);
            }

            return R.ok("操作成功", re);
        }else {
            return R.ok(respCodeDesc, null);
        }
    }

    @GetMapping("/preauthcmpcancel")//预授权完成撤销
    public R<Object> preauthcmpcancel(String termNoIn, String mchntNoIn,
                                      String transAmt, String priAcctNoHit, String oriPlatOrderId,String params) {

        String url = "https://api-mop.chinaums.com/v1/upsc/preauthservice/preauthcmpcancel";

        String now = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMAT);
        String year = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_FORMAT);
        int randomNumber = ThreadLocalRandom.current().nextInt(100000, 999999);
        String transOrderId = year + termBatchNoOut + randomNumber;
        JSONObject json = new JSONObject();
        json.set("termNoIn", termNoIn);
        json.set("mchntNoIn", mchntNoIn);
        json.set("transType", "auth.cmp.cancel");
        json.set("posEntryModeCode", "012");
        BigDecimal s=new BigDecimal(transAmt).multiply(new BigDecimal("100")).setScale(0);
        json.set("transAmt", s.toString());
//        json.set("transAmt", transAmt);
        json.set("currency", "156");
        json.set("termRead", "6");
        json.set("termVersion", "32");
        json.set("oriPlatOrderId", oriPlatOrderId);
        json.set("transOrderId", transOrderId);
        json.set("priAcctNoHit", priAcctNoHit);

        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
        String authorization = getAuthorization(appId, appKey, now, IdUtil.fastSimpleUUID(), JSONUtil.toJsonStr(json));
        String re = HttpRequest.post(url)
            .body(JSONUtil.toJsonStr(json))
            .header("authorization", authorization).execute().body();
        Map<String,String> map=(Map) JSONUtil.parseObj(re);
        String respCodeDesc=map.get("respCodeDesc");
        if (respCodeDesc.equals("交易成功")){
            try {
                Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

                String urls = "jdbc:sqlserver://127.0.0.1:1433;DatabaseName=Production;trustServerCertificate=true;";
                Connection conn = DriverManager.getConnection(urls, "sa", "xuquan666");
                String[] paramList = params.split(",");
                String bankTrxCode = paramList[1];
                String Amount = paramList[2];  //金额
                System.out.println("但是但是多所"+Amount);
//                String pay = paramList[4];
                double i = Double.parseDouble(Amount);
                double negativeNumber = -i;  // 负数
                String reservationCode = paramList[0];   //预定号


                BankCreditCard bankCreditCard = deptService.getBankCreditCard(bankTrxCode);

                PreparedStatement ps = conn.prepareStatement("{call dbo.ftPayment(?,?,?,?,?,?,?,?,?,?,?)}");
                ps.setString(1, "9004");
                ps.setString(2, String.valueOf(negativeNumber));
                ps.setString(3, "0|0|0");
                ps.setString(4, null);
                ps.setString(5, null);
                ps.setString(6, null);
                ps.setString(7, "*");
                ps.setString(8, "*");
                ps.setInt(9, 1);
                ps.setInt(10, Integer.parseInt(reservationCode));
                ps.setString(11, "Admin");


                ps.execute();
            }catch (Exception e){
                e.printStackTrace();
                return R.ok("接口异常"+e.getMessage(), null);
            }
            return R.ok("操作成功", re);
        }else {
            return R.ok(respCodeDesc, null);
        }

    }


    @GetMapping("/refund")
    public R<Object> refund(String termNoIn, String mchntNoIn,
                            String transAmt, String oriTransDate, String priAcctNoHit, String oriPlatOrderId) {

        String url = "https://api-mop.chinaums.com/v1/upsc/refundservice/refund";

        String now = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMAT);
        String year = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_FORMAT);
        int randomNumber = ThreadLocalRandom.current().nextInt(100000, 999999);
        String transOrderId = year + termBatchNoOut + randomNumber;
        JSONObject json = new JSONObject();
        json.set("termNoIn", termNoIn);
        json.set("mchntNoIn", mchntNoIn);
        json.set("transType", "refund");

        json.set("posEntryModeCode", "012");
        BigDecimal s=new BigDecimal(transAmt).multiply(new BigDecimal("100")).setScale(0);
        json.set("transAmt", s.toString());
        json.set("currency", "156");
        json.set("termRead", "6");
        json.set("icCondCode", "0");
        json.set("termVersion", "32");

        json.set("oriTransDate", oriTransDate);
        json.set("transOrderId", transOrderId);
        json.set("priAcctNoHit", priAcctNoHit);
        json.set("oriPlatOrderId", oriPlatOrderId);


        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
        String authorization = getAuthorization(appId, appKey, now, IdUtil.fastSimpleUUID(), JSONUtil.toJsonStr(json));

        String re = HttpRequest.post(url)
            .body(JSONUtil.toJsonStr(json))
            .header("authorization", authorization).execute().body();
        return R.ok("操作成功", re);
    }


    @GetMapping("/preauthcance")
    public R<Object> preauthcance(String termNoIn, String authNo, String mchntNoIn,
                                  String transAmt, String priAcctNoHit,String params) {

        String url = "https://api-mop.chinaums.com/v1/upsc/preauthservice/preauthcancel";

        String now = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMAT);
        String year = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_FORMAT);
        int randomNumber = ThreadLocalRandom.current().nextInt(100000, 999999);
        String transOrderId = year + termBatchNoOut + randomNumber;
        JSONObject json = new JSONObject();
        json.set("termNoIn", termNoIn);
        json.set("mchntNoIn", mchntNoIn);
        json.set("transType", "auth.cancel");
        json.set("posEntryModeCode", "012");
        BigDecimal s=new BigDecimal(transAmt).multiply(new BigDecimal("100")).setScale(0);
        json.set("transAmt", s.toString());
        json.set("currency", "156");
        json.set("termRead", "5");
        json.set("authNo", authNo);

        json.set("termVersion", "32");
        json.set("transOrderId", transOrderId);
        json.set("priAcctNoHit", priAcctNoHit);


        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
        String authorization = getAuthorization(appId, appKey, now, IdUtil.fastSimpleUUID(), JSONUtil.toJsonStr(json));

        String re = HttpRequest.post(url)
            .body(JSONUtil.toJsonStr(json))
            .header("authorization", authorization).execute().body();
        Map<String,String> map=(Map) JSONUtil.parseObj(re);
        String respCodeDesc=map.get("respCodeDesc");
        if (respCodeDesc.equals("交易成功")){
            String[] paramList = params.split(",");
            String bankTrxCode = paramList[0];
            deptService.deleteBank(bankTrxCode);
            deptService.deleteBankCard(bankTrxCode);
        }

        return R.ok("操作成功", re);
    }
    @GetMapping("/preauthorize")
    public R<Object> preauthorize(String transactionAmount,String payMode,String payCode,String params,String money) throws Exception {
        String url = "https://api-mop.chinaums.com/v1/poslink/transaction/preauthorization/preauthorize";
        ConfigBean configBean = new ConfigBean();
        OpenApiContext context = new OpenApiContext();
        LocalTime now = LocalTime.now();
        String systemTraceNum=now.format(formatter);

        String request =
            "{" +
                "\"merchantCode\":\"" + merchantCode + "\"," +
                "\"terminalCode\":\"" + terminalCode + "\"," +
                "\"systemTraceNum\":\"" + systemTraceNum + "\"," +
                "\"transactionAmount\":\"" + transactionAmount + "\"," +
                "\"transactionCurrencyCode\":\"" + transactionCurrencyCode + "\"," +
                "\"payMode\":\"" + payMode + "\"," +
                "\"payCode\":\"" + payCode + "\"," +
                "\"ip\":\"" + ip + "\"," +
                "\"deviceType\":\"" + deviceType + "\"" +
                "}";
        context.setStartTime(System.currentTimeMillis());
        context.setRequestId(UUID.randomUUID().toString().replace("-", ""));
        context.setOpenServUrl(url.split("/v")[0].concat("/"));
        System.out.println(context.getOpenServUrl() + "========================================================================================================================");
        context.setApiServiceUrl(url);
        context.setVersion(url.split("/")[3]);
        context.setAppId(appId);
        context.setAppKey(appKey);
        context.setConfigBean(configBean);
        context.setServiceCode(url.split("/v")[1].substring(1));
        OpenApiCache.getCurrentToken(context);
        String s = HttpTransport.getInstance().doPost(context, request);
        Map maps = (Map) JSONUtil.parse(s);
        if (maps.get("errCode").equals("00")) {
            System.out.println(maps.get("orderId"));
            SysBank sysBank = new SysBank();
            BankCreditCard bankCreditCard = new BankCreditCard();

            String[] paramList = params.split(",");
            String reservationCode = paramList[0];   //预定号

            //[11]
            bankCreditCard.setCode((String) maps.get("orderId"));
            bankCreditCard.setFolioID(reservationCode);
            bankCreditCard.setPosAmount(money);
            bankCreditCard.setOperator("Admin");
            bankCreditCard.setPosType("*");
            bankCreditCard.setCreditCardNO("bc");
            deptService.insertBankCard(bankCreditCard);

            sysBank.setReservationCode(reservationCode);
            sysBank.setInsertUser("Admin");
            sysBank.setPaymentType("GBD");
            sysBank.setCreditCardNo("bc");
            sysBank.setApproveCode((String) maps.get("orderId"));
            sysBank.setApproveAmount(money);
            sysBank.setBankTrxCode((String) maps.get("orderId"));
            //insert into rvCreditCard (ReservationCode,PaymentType,CreditCardNo,ApproveAmount,ApproveCode,InsertUser,InsertTime)
            //       select @ReservationCode,@PaymentType,@CreditCardNo,@ApproveAmount,@ApproveCode,@InsertUser,@InsertTime,
            deptService.insertBank(sysBank);
            return R.ok("操作成功", maps.get("errInfo"));
        }
            return R.ok("操作失败", maps.get("errInfo"));
        }







    public static void main(String[] args) throws Exception {
        String url = "https://api-mop.chinaums.com/v1/upsc/preauthservice/preauthcmp";

        String now = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMAT);

        String json = "{\n" +
            "\n" +
            "    \"termNoIn\": \"89990299\",\n" +
            "    \"mchntNoIn\": \"898460170111840\",\n" +
            "    \"transType\": \"auth.cmp\",\n" +
            "    \"posEntryModeCode\": \"012\",\n" +
            "    \"transAmt\": \"1\",\n" +
            "    \"currency\": \"156\",\n" +
            "    \"termRead\": \"6\",\n" +
            "    \"termVersion\": \"32\",\n" +
            "    \"authNo\": \"252183\",\n" +
            "    \"transOrderId\": \"20231130000001123457\",\n" +
            "    \"priAcctNoHit\": \"622203*********2636\",\n" +
            "    \"oriPlatOrderId\":\"135959241150\"\n" +
            "\n" +
            "}";


        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
        String authorization = getAuthorization(appId, appKey, now, IdUtil.fastSimpleUUID(), json);

        String s = HttpRequest.post(url)
            .body(json)
            .header("authorization", authorization).execute().body();
        System.out.println(s);

    }


    @SneakyThrows
    static String getAuthorization(String appid, String appkey, String timestamp, String nonce, String body) {
        byte[] data = body.getBytes(StandardCharsets.UTF_8);
        InputStream is = new ByteArrayInputStream(data);
        String testSH = DigestUtils.sha256Hex(is);
        String s1 = appid + timestamp + nonce + testSH;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(appkey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] localSignature = mac.doFinal(s1.getBytes(StandardCharsets.UTF_8));
        String localSignatureStr = Base64.encodeBase64String(localSignature);
        return "OPEN-BODY-SIG AppId=" + "\"" + appid + "\"" + ", Timestamp=" + "\"" + timestamp + "\"" + ", Nonce=" + "\"" + nonce + "\"" + ", Signature=" + "\"" + localSignatureStr + "\"";
    }


}


